package transport;

import misc.AllocCache;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

/**
 * Protocol class supports automatic creation of protocols depending on connection.
 */
public abstract class Protocol {
    private final List<Agent> agents = new LinkedList<Agent>();

    public final synchronized void registerAgent(Agent agent) {
        agents.add(agent);
    }

    public final synchronized void unregisterAgent(Agent agent) {
        agents.remove(agent);
    }

    public final void listen(int port) throws IOException {
        Agent agent = new ListenerAgent(this, port);
        agent.start();
    }

    public final void connect(String host, int port) throws IOException {
        Socket socket = new Socket();
        socket.connect(new InetSocketAddress(host, port));

        Agent agent = createProtocolAgent(socket);
        agent.start();
    }

    public final synchronized void stopAll() {
        for (Agent agent : agents) {
            agent.stop();
        }

        agents.clear();
    }

    public abstract ProtocolAgent createProtocolAgent(Socket socket) throws IOException;

    public final AllocCache<ByteBuffer> buffersCache = new AllocCache<ByteBuffer> (
            new AllocCache.Factory<ByteBuffer>() {
                public ByteBuffer create() {
                    return ByteBuffer.allocate(ProtocolAgent.BUFFER_SIZE);
                }
                public void release(ByteBuffer buffer) {
                    buffer.clear();
                }
            });
}
